home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / gen / bstone / borlandc / bstone_m.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-18  |  21.7 KB  |  868 lines

  1. /************************************************************************/
  2. /* BSTONE operations module                                             */
  3. /************************************************************************/
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <alloc.h>
  9. #include "t_cio.h"
  10. #include "t_lex.h"
  11. #include "vector.h"
  12. #include "bstone_m.h"
  13.  
  14. CMD_LINE program[MAX_LINES];
  15. int gosub_stack[MAX_LINES/10];
  16. int gosub_ptr=0;
  17. int cont_line=-1;
  18. int program_ctr=-1;
  19. int transl_flag=0;
  20. int cmdl,flev;
  21. FILE *fp[10];
  22. char cline[LSIZE];
  23. int clinep;
  24. char *clines;
  25. char err_msg[BSIZE];
  26. char tmp_line[LSIZE];
  27.  
  28. static int bdebug;
  29.  
  30. /* Error messages etc.                                                 */
  31. /* err: Error number.                                                  */
  32. /*      0: regular message                                             */
  33. /*      1: print error message                                         */
  34. /*      2: dito, read line until end                                   */
  35. /*      3: Syntax error                                                */
  36. /*      4: dito, read line until end                                   */
  37. /*      5: Lex error, read line until end                              */
  38. /*      6: Expression error                                            */
  39. /*      7: Error during execution                                      */
  40. /*      8: Break requested                                             */
  41. void basic_error(int err)
  42. {
  43.  LEX *lex;
  44.  
  45.  if((program_ctr>0) && (program_ctr<MAX_LINES))
  46.    fprintf(stderr,"@L%d: ",program[program_ctr-1].n);
  47.  else
  48.    fprintf(stderr,"@C%d: ",cmdl);
  49.  fprintf(stderr,"ERROR: ",err);
  50.  if(errlog!=stderr)
  51.    {
  52.     fprintf(errlog,"\nERROR(%d) at line %d or command %d ",
  53.            err,(program_ctr>0) ? program[program_ctr-1].n : -1,cmdl);
  54.     fprintf(errlog,"\nLex-Msg: %s",t_pos());
  55.    }
  56.  switch(err)
  57.    {
  58.     case 0:   fprintf(stderr,"OK."); break;
  59.     case 1:   fprintf(stderr,"%s",err_msg);
  60.           if(errlog!=stderr) fprintf(errlog,"%s",err_msg); break;
  61.     case 2:   fprintf(stderr,"%s",err_msg);
  62.           if(errlog!=stderr) fprintf(errlog,"%s",err_msg); goto la_err1;
  63.     case 3:   fprintf(stderr,"Syntax analysis failed."); break;
  64.     case 4:   fprintf(stderr,"Syntax analysis failed."); goto la_err1;
  65.     case 5:   fprintf(stderr,"Lexical analysis failed."); goto la_err1;
  66.     case 6:   fprintf(stderr,"Wrong expression."); break;
  67.     case 7:   fprintf(stderr,"Error occured during execution."); break;
  68.     case 8:   fprintf(stderr,"Break requested."); break;
  69.     default:  fprintf(stderr,"Unknown.");
  70.     la_err1:                             /* read line until end */
  71.           lex=t_lex(NULL,LEX_PUSH);
  72.           lex=t_lex(NULL,NO_FORCE);
  73.           while((lex->typ!=EOLN) && (lex->typ!=EOLX))
  74.         {
  75.          lex=t_lex(NULL,NO_FORCE);
  76.         }
  77.           break;
  78.    }
  79.  fprintf(stderr,"\n");
  80.  return;
  81. }
  82.  
  83. /* clear program pointer etc.                                          */
  84. void clear_program(void)
  85. {
  86.  ybdebug=bdebug;
  87.  gosub_ptr=0;
  88.  program_ctr=-1;
  89.  cont_line=-1;
  90.  errlogz=stderr;
  91.  return;
  92. }
  93.  
  94. /* delete vars                                                         */
  95. void del_vars(T_NODE * tnode)
  96. {
  97.  DIM_H *dm;
  98.  
  99.  if(tnode->c>0) switch(tnode->c)
  100.    {
  101.     case B_FLD: dm=(DIM_H *)(tnode->p);
  102. #ifdef __TURBOC__
  103.         farfree(dm->f);
  104. #else
  105.         free(dm->f);
  106. #endif
  107.         break;
  108.     default:    break;
  109.    }
  110.  tnode->p=(void *)NULL;
  111.  return;
  112. }
  113.  
  114. /* Deletes program and variables                                         */
  115. void new(void)
  116. {
  117.  int i;
  118.  POV_OBJ *pv;
  119.  
  120.  t_symdel(del_vars);
  121.  gosub_ptr=0;
  122.  program_ctr=-1;
  123.  cont_line=-1;
  124.  
  125.  for(i=0;i<MAX_LINES;i++)
  126.    {
  127.     program[i].n=-1;
  128.     if(program[i].s!=(char *)NULL) free(program[i].s);
  129.     program[i].s=(char *)NULL;
  130.    }
  131.  
  132.  for(i=0;i<PSIZE;i++)
  133.    if((pv=obj_all[i])!=(POV_OBJ *)NULL)
  134.      { if(pv->s!=(char *)NULL) free(pv->s);
  135.        free(pv);
  136.        obj_all[i]=(POV_OBJ *)NULL;
  137.      }
  138.  return;
  139. }
  140.  
  141. /* finds counter for line equal or greater n                           */
  142. int search_line(int n)
  143. {
  144.  int i,k,l;
  145.  
  146.  i=MAX_LINES-1; k=MAX_LINES/2;
  147.  do { l=i-k; if((unsigned)(program[l].n)>=n) i=l; k>>=1; }
  148.  while(k);
  149.  return(i);
  150. }
  151.  
  152. /* inserts line s at n, allocates memory for s                          */
  153. /* if s==NULL, delete line n                                            */
  154. int insert_line(int n, char *s)
  155. {
  156.  int l,k;
  157.  static char msg[]={"Inserting/Deleting Line"};
  158.  if(*s==(char)0) s=(char *)NULL;
  159.  
  160.  l=search_line(n);
  161.  if(bdebug) fprintf(errlog,"%s %d (next %d)\n",msg,n,program[l].n);
  162.  if(program[l].n==n)                          /* line existing yet       */
  163.    {
  164.     if(program[l].s!=(char *)NULL) free(program[l].s);
  165.     if(s==(char *)NULL)                       /* delete line             */
  166.       {
  167.        for(k=l;k<MAX_LINES-1;k++)
  168.      {
  169.       program[k].n=program[k+1].n;
  170.       program[k].s=program[k+1].s;
  171.      }
  172.        program[MAX_LINES-1].n=-1;
  173.        program[MAX_LINES-1].s=(char *)NULL;
  174.       }
  175.     }
  176.  else if(s!=(char *)NULL)
  177.    {
  178.     if(program[MAX_LINES-1].s!=(char *)NULL) t_error(msg,4);
  179.     for(k=MAX_LINES-1;k>l;k--)
  180.       {
  181.        program[k].n=program[k-1].n;
  182.        program[k].s=program[k-1].s;
  183.       }
  184.    }
  185.  if(s!=(char *)NULL)
  186.    {
  187.     k=strlen(s);
  188.     if((program[l].s=(char *)malloc((k+1)*sizeof(char)))==(char *)NULL)
  189.       t_error(msg,1);
  190.     strcpy(program[l].s,s);
  191.     program[l].n=n;
  192.    }
  193.  return;
  194. }
  195.  
  196. /* translates cmd-line into internal representation                       */
  197. /* returns NULL, if error                                                 */
  198. char *translate_line(void)
  199. {
  200.  static char msg[]={"Translating Line"};
  201.  int err;
  202.  
  203.  if(bdebug) fprintf(errlog,"%s: ",msg);
  204.  clinep=0; transl_flag=1;
  205.  
  206.  /* call parser here */
  207.  /* on error call basic_error(4) */
  208.  err=0;
  209.  if(yyparse())
  210.   {
  211.    basic_error(4);
  212.    err=1;
  213.   }
  214.  cline[clinep]=(char)0;
  215.  transl_flag=0;
  216.  if(clinep>=LSIZE-1) t_error(msg,4);
  217.  if(bdebug) fprintf(errlog,"%s\n",retransl_line(cline));
  218.  if(err) return((char *)NULL);
  219.  return(cline);
  220. }
  221.  
  222.  
  223. /* re-translates cmd-line from internal representation                    */
  224. char *retransl_line(char *dline)
  225. {
  226.  static char msg[]={"Retranslating Line"};
  227.  int p1,p2,c,n,i,k;
  228.  int jmp_flag;
  229.  char *p,*s,cc;
  230.  T_NODE *tnode;
  231.  
  232.  if(dline==(char *)NULL) { tmp_line[0]=(char)0; return(tmp_line); }
  233.  jmp_flag=0;
  234.  for(p1=0,p2=0;*(dline+p2);p2++,p1=strlen(tmp_line))
  235.    {
  236.     c=(*((unsigned char *)dline+p2)); p=tmp_line+p1;
  237.     if(c>=128)                 /* Token? */
  238.       {
  239.        c=VALTOKEN(c);
  240.        switch(c)
  241.      {
  242.       case B_NUM:   case B_VAL:   case B_OBJ:
  243.       case B_VEC:   case B_STR:
  244.             if(!p2) { sprintf(p," LET "); p+=5; }
  245.             s=dline+p2+1;
  246.             n=GET4HEX(s); p2+=4;
  247.             if((tnode=t_symfind(n))==(T_NODE *)NULL)
  248.               {
  249.                if(bdebug) { t_symwalk(-1,symdebug); }
  250.                fprintf(errlog,"Did not find symbol #%4s/%d\n",s,n);
  251.                t_error(msg,3);
  252.               }
  253.             switch(c)
  254.               {
  255.                case B_STR:
  256.                 s=(tnode->s);
  257.                 for(i=0,n=0;i<strlen(s);i++)
  258.                   { cc=*(s+i);
  259.                     switch(cc)
  260.                       { case '\n': *(p+(n++))='\\';
  261.                            *(p+(n++))='n';
  262.                            break;
  263.                     default:   *(p+(n++))=cc;
  264.                            break;
  265.                       }
  266.                   }
  267.                 *(p+n)='"'; *(p+n+1)=(char)0;
  268.                 break;
  269.                case B_NUM:
  270.                 k=search_line((int)*(double *)(tnode->p));
  271.                 if((transl_flag!=2) || !jmp_flag)
  272.                   sprintf(p,"%s",(tnode->s)+1);
  273.                 else
  274.                   sprintf(p,"%d",10*(k+1));
  275.                 jmp_flag=0;
  276.                 break;
  277.                default: sprintf(p,"%s",tnode->s);
  278.                 break;
  279.               }
  280.             break;
  281.  
  282.       case B_FKT:
  283.             p2+=1;
  284.             c=(*((unsigned char *)dline+p2));
  285.             c=VALTOKEN(c);
  286.  
  287.       case RND:     case ABS:    case V0:
  288.       case VX:      case VY:     case VZ:
  289.       case PLANE:
  290.             sprintf(p,"%s",t_tokenstr(c));
  291.             break;
  292.  
  293.       case GOTO:    case GOSUB:
  294.             sprintf(p," %s ",t_tokenstr(c));
  295.             jmp_flag=1;
  296.             break;
  297.  
  298.       default:  sprintf(p," %s ",t_tokenstr(c));
  299.             break;
  300.      }
  301.       }
  302.     else
  303.       {
  304.        *p=c; *(p+1)=(char)(0);
  305.       }
  306.    }
  307.  if((p1>=LSIZE-1) || (p2>=LSIZE-1)) t_error(msg,4);
  308.  tmp_line[p1]=(char)0;
  309.  return(tmp_line);
  310. }
  311.  
  312. /* executes command                                                       */
  313. void exec_line(char *dline)
  314. {
  315.  if(dline==(char *)NULL) return;
  316.  clines=dline; transl_flag=0;
  317.  
  318.  do
  319.    {
  320.     clinep=0;
  321.     if(program_ctr>=0)
  322.       {
  323.        clines=program[program_ctr].s;
  324.        program_ctr++;              /* Increasing program counter        */
  325.       }
  326.     /* Parse & execute */
  327.     if(yyparse()) { basic_error(7); program_ctr=-1; }
  328.  
  329.     if(program_ctr>=0)
  330.       if((program[program_ctr].n<0) || (program_ctr>=MAX_LINES))
  331.     { program_ctr=-1; }
  332.     if(load_flag)
  333.       {
  334.        load_flag=0;
  335.        t_setfep(fp[flev],3L);
  336.        program_ctr=-1;
  337.       }
  338.  
  339.    }
  340.  while(program_ctr>=0);
  341.  
  342.  return;
  343. }
  344.  
  345. /* increases number of parents */
  346. void add_objz(POV_OBJ *pv)
  347. {
  348.  int n; char *s;
  349.  static char msg[]="Adding new object parent.";
  350.  
  351.  if(pv==(POV_OBJ *)NULL) t_error(msg,3);
  352.  if(pv->tex!=(POV_OBJ *)NULL) { add_objz(pv->tex); pv->tex->cnt+=1; }
  353.  if(pv->bound!=(POV_OBJ *)NULL) { add_objz(pv->bound); pv->bound->cnt+=1; }
  354.  if(pv->c==0) return;
  355.  if(pv->s==(char *)NULL) t_error(msg,4);
  356.  
  357.  for(s=pv->s;*s;s+=5)
  358.    { n=GET4HEX(s+1);
  359.      if((n<0) || (n>=PSIZE) || (obj_all[n]==(POV_OBJ *)NULL))
  360.        t_error(msg,3);
  361.      obj_all[n]->cnt+=1;
  362.      add_objz(obj_all[n]);
  363.    }
  364.  return;
  365. }
  366.  
  367. POV_OBJ *obj_asn(POV_OBJ *pv1, POV_OBJ *pv2)
  368. {
  369.  int i;
  370.  POV_OBJ pvx;
  371.  static char msg[]="Assignment of objects.";
  372.  
  373.  if(pv2==(POV_OBJ *)NULL) t_error(msg,3);
  374.  
  375.  pvx.c=pv2->c;
  376.  for(i=0;i<3;i++)
  377.    {
  378.     pvx.b[i]=pv2->b[i]; pvx.u[i]=pv2->u[i];
  379.     pvx.v[i]=pv2->v[i]; pvx.w[i]=pv2->w[i];
  380.    }
  381.  pvx.s=cp_str(pv2->s);
  382.  pvx.tex=pv2->tex;
  383.  pvx.bound=pv2->bound;
  384.  
  385.  if(pv2->cnt>=0) add_objz(pv2);  /* pvx is new parent of pv2 */
  386.  /* objects with count < 0 are temporary !!                */
  387.  
  388.  if(pv1==(POV_OBJ *)NULL) pv1=new_obj();
  389.  else free_obj(pv1);
  390.  
  391.  pv1->cnt=1;
  392.  pv1->c=pvx.c;
  393.  for(i=0;i<3;i++)
  394.    {
  395.     pv1->b[i]=pvx.b[i]; pv1->u[i]=pvx.u[i];
  396.     pv1->v[i]=pvx.v[i]; pv1->w[i]=pvx.w[i];
  397.    }
  398.  pv1->s=pvx.s;
  399.  pv1->tex=pvx.tex;
  400.  pv1->bound=pvx.bound;
  401.  
  402.  return(pv1);
  403. }
  404.  
  405.  
  406. POV_OBJ *add_obj(POV_OBJ *pv1,POV_OBJ *pv2)
  407. {
  408.  POV_OBJ *pv; int n,i,n1,n2;
  409.  char *s;
  410.  static char msg[]="Adding object.";
  411.  
  412.  if(pv1==(POV_OBJ *)NULL)
  413.    { pv1=new_obj(); pv1->c=1; }
  414.  else
  415.    if(pv1->c==0)
  416.      { pv=add_obj((POV_OBJ *)NULL,pv1);
  417.        pv=add_obj(pv,pv2);
  418.        return(pv);
  419.      }
  420.  
  421.  if(pv2==(POV_OBJ *)NULL) return(pv1);
  422.  
  423.  n=new_objz();
  424.  pv=obj_all[n];
  425.  pv->c=pv2->c;
  426.  for(i=0;i<3;i++)
  427.    {
  428.     pv->b[i]=pv2->b[i];  pv->u[i]=pv2->u[i];
  429.     pv->v[i]=pv2->v[i];  pv->w[i]=pv2->w[i];
  430.    }
  431.  pv->s=cp_str(pv2->s);
  432.  pv->tex=pv2->tex;
  433.  pv->bound=pv2->bound;
  434.  
  435.  add_objz(pv2);  /* pv is new parent of pv2 */
  436.  sprintf(tmp_line,":%04.4X",n);
  437.  
  438.  /* cat string */
  439.  if(pv1->s==(char *)NULL) pv1->s=cp_str(tmp_line);
  440.  else
  441.    {
  442.     n1=strlen(pv1->s); n2=strlen(tmp_line);
  443.     n=(n1+n2)/SSIZE;
  444.     if(n==n1/SSIZE) strcat(pv1->s,tmp_line);
  445.     else
  446.       {
  447.        n=(n+1)*SSIZE;
  448.        if((s=(char *)malloc(n))==(char *)NULL) t_error(msg,1);
  449.        strcpy(s,pv1->s);
  450.        strcat(s,tmp_line);
  451.        free(pv1->s);
  452.        pv1->s=s;
  453.       }
  454.    }
  455.  return(pv1);
  456. }
  457.  
  458. POV_OBJ *new_obj(void) { return(obj_all[new_objz()]); }
  459.  
  460. int new_objz(void)
  461. {
  462.  POV_OBJ *pv;
  463.  int k;
  464.  static char msg[]="Creating new object";
  465.  
  466.  for(k=0,pv=(POV_OBJ *)NULL;pv==(POV_OBJ *)NULL;k++)
  467.    {
  468.     if(k>=PSIZE) t_error(msg,3);
  469.     if(obj_all[k]==(POV_OBJ *)NULL)
  470.       {
  471.        if((pv=(POV_OBJ *)malloc(sizeof(POV_OBJ)))==(void *)NULL)
  472.      t_error(msg,1);
  473.        obj_all[k]=pv;
  474.       }
  475.     else
  476.       if(obj_all[k]->cnt==0) pv=obj_all[k];
  477.    }
  478.  
  479.  pv->c=(char)0;
  480.  pv->cnt=1;
  481.  pv->tex=(POV_OBJ *)NULL;
  482.  pv->bound=(POV_OBJ *)NULL;
  483.  (pv->b)[0]=0; (pv->b)[1]=0; (pv->b)[2]=0;
  484.  (pv->u)[0]=1; (pv->u)[1]=0; (pv->u)[2]=0;
  485.  (pv->v)[0]=0; (pv->v)[1]=1; (pv->v)[2]=0;
  486.  (pv->w)[0]=0; (pv->w)[1]=0; (pv->w)[2]=1;
  487.  pv->s=(char *)NULL;
  488.  return(k-1);
  489. }
  490.  
  491.  
  492. char *cp_str(char *s)
  493. {
  494.  static char msg[]="Copying string.";
  495.  char *s1; int n;
  496.  
  497.  if(s==(char *)NULL) return(s);
  498.  n=strlen(s);
  499.  n=(n/SSIZE+1)*SSIZE;
  500.  if((s1=(char *)malloc(n))==(char *)NULL) t_error(msg,1);
  501.  strcpy(s1,s);
  502.  return(s1);
  503. }
  504.  
  505. FILE *save_program( int n1, int n2, char *str )
  506. {
  507.  int i;
  508.  static FILE *savep;
  509.  
  510.  if((savep=fopen(str,"w"))==NULL) return(NULL);
  511.  for(i=n1; (i<=n2) && (program[i].n>=0); i++)
  512.    {
  513.     fprintf(savep,"%-6d ",transl_flag!=2 ? program[i].n : 10*(i+1));
  514.     fprintf(savep,"%s\n",retransl_line(program[i].s));
  515.    }
  516.  fclose(savep);
  517.  return(savep);
  518. }
  519.  
  520. int get4hex(char *s)
  521. {
  522.  int i,n;
  523.  char c;
  524.  static char msg[]="Decoding hex number.";
  525.  
  526.  for(i=0,n=0;i<4;i++)
  527.    {
  528.     c=*(s+i);
  529.     c=(c>='A') ? (c-'A'+10) : (c-'0');
  530.     if(c&~0XF) t_error(msg,3);
  531.     n=(n<<4)+c;
  532.    }
  533.  return(n);
  534. }
  535.  
  536.  
  537. void free_obj(POV_OBJ *pv)
  538. {
  539.   if(pv->cnt!=1) t_error("Object cannot be deleted. It is used.",3);
  540.   del_obj(pv); pv->cnt=1;
  541.   return;
  542. }
  543.  
  544. void del_obj(POV_OBJ *pv)
  545. {
  546.  char *s; int n;
  547.  char msg[]="Deleting object.";
  548.  
  549.  if(pv==(POV_OBJ *)NULL) t_error(msg,3);
  550.  if(pv->cnt<1) t_error(msg,3);
  551.  if(pv->c>0)
  552.    {
  553.     if(pv->s==(char *)NULL) t_error(msg,4);
  554.     for(s=pv->s;*s;s+=5)
  555.       {
  556.        n=GET4HEX(s+1);
  557.        del_obj(obj_all[n]);
  558.       }
  559.    }
  560.  
  561.  if(pv->tex!=(POV_OBJ *)NULL) del_obj(pv->tex);
  562.  if(pv->bound!=(POV_OBJ *)NULL) del_obj(pv->bound);
  563.  if(pv->cnt==1)
  564.    {
  565.     if(pv->s!=(char *)NULL) free(pv->s); pv->s=(char *)NULL;
  566.     pv->c=0;
  567.     (pv->b)[0]=0; (pv->b)[1]=0; (pv->b)[2]=0;
  568.     (pv->u)[0]=1; (pv->u)[1]=0; (pv->u)[2]=0;
  569.     (pv->v)[0]=0; (pv->v)[1]=1; (pv->v)[2]=0;
  570.     (pv->w)[0]=0; (pv->w)[1]=0; (pv->w)[2]=1;
  571.     pv->tex=(POV_OBJ *)NULL;
  572.     pv->bound=(POV_OBJ *)NULL;
  573.    }
  574.  pv->cnt-=1;
  575.  return;
  576. }
  577.  
  578. /* Makes a copy of texture and bound, if more than 1 parent */
  579. POV_OBJ *cp_tbx(POV_OBJ *p)
  580. {
  581.  POV_OBJ *pv;
  582.  
  583.  pv=p->tex;
  584.  if(pv!=(POV_OBJ *)NULL)
  585.    if(pv->cnt>1)
  586.      { p->tex=obj_asn((POV_OBJ *)NULL,pv);
  587.        del_obj(pv); }
  588.  pv=p->bound;
  589.  if(pv!=(POV_OBJ *)NULL)
  590.    if(pv->cnt>1)
  591.      { p->bound=obj_asn((POV_OBJ *)NULL,pv);
  592.        del_obj(pv); }
  593.  return(p);
  594. }
  595.  
  596. POV_OBJ *yscale1(POV_OBJ *p,VECTOR v)
  597. { if(p==(POV_OBJ *)NULL) return(p);
  598.   scale(p->b,v,p->b); scale(p->u,v,p->u);
  599.   scale(p->v,v,p->v); scale(p->w,v,p->w);
  600.   return(p); }
  601.  
  602. POV_OBJ *yscale2(POV_OBJ *p,VECTOR v)
  603. { if(p==(POV_OBJ *)NULL) return(p);
  604.   vecscale(p->u,v[0],p->u); vecscale(p->v,v[1],p->v);
  605.   vecscale(p->w,v[2],p->w);
  606.   return(p); }
  607.  
  608. POV_OBJ *yrot1(POV_OBJ *p,VECTOR v)
  609. { if(p==(POV_OBJ *)NULL) return(p);
  610.   rotxyz(p->b,v,p->b); rotxyz(p->u,v,p->u);
  611.   rotxyz(p->v,v,p->v); rotxyz(p->w,v,p->w);
  612.   return(p); }
  613.  
  614. POV_OBJ *yrot2(POV_OBJ *p,VECTOR v)
  615. { VECTOR vu,vv,vw,vt;
  616.   if(p==(POV_OBJ *)NULL) return(p);
  617.   vecx(vu);            vecy(vv);           vecz(vw);
  618.   rotxyz(vu,v,vu);     rotxyz(vv,v,vv);    rotxyz(vw,v,vw);
  619.   vt[0]=vecabs(p->u);  vt[1]=vecabs(p->v); vt[2]=vecabs(p->w);
  620.   vecscale(p->u,1/vt[0],p->u);
  621.   vecscale(p->v,1/vt[1],p->v);
  622.   vecscale(p->w,1/vt[2],p->w);
  623.   transformc(vu,vu,p->u,p->v,p->w);
  624.   transformc(vv,vv,p->u,p->v,p->w);
  625.   transformc(vw,vw,p->u,p->v,p->w);
  626.   vecscale(p->u,vt[0],vu);
  627.   vecscale(p->v,vt[1],vv);
  628.   vecscale(p->w,vt[2],vw);
  629.   return(p); }
  630.  
  631. POV_OBJ *ytransl1(POV_OBJ *p,VECTOR v)
  632. { if(p==(POV_OBJ *)NULL) return(p);
  633.   vecadd(p->b,v,p->b);
  634.   return(p); }
  635.  
  636. POV_OBJ *ytransl2(POV_OBJ *p,VECTOR v)
  637. { VECTOR vt;
  638.   if(p==(POV_OBJ *)NULL) return(p);
  639.   transformc(vt,v,p->u,p->v,p->w);
  640.   vecadd(p->b,vt,p->b);
  641.   return(p); }
  642.  
  643.  
  644.  
  645. /* makes an object fitting into it's bounds                    */
  646. POV_OBJ *fit_obj(POV_OBJ *pv)
  647. {
  648.  char *s; int n;
  649.  VECTOR p0,px,py,pz;
  650.  POV_OBJ *p,*q;
  651.  double d,db,dx0,dx1,dy0,dy1,dz0,dz1;
  652.  
  653.  if(pv->bound==(POV_OBJ *)NULL) pv->bound=new_obj();
  654.  if(pv->c==0) return(pv);
  655.  dx0=dx1=dy0=dy1=dz0=dz1=0; /* stop warning */
  656.  
  657.  for(s=pv->s,n=0;*s;s+=5,n++)
  658.    {
  659.     p=obj_all[get4hex(s+1)];
  660.     q=p->bound;
  661.     if(q==(POV_OBJ *)NULL)
  662.       {
  663.        vecasn(p0,p->b); vecasn(px,p->u); vecasn(py,p->v); vecasn(pz,p->w);
  664.       }
  665.     else
  666.       {
  667.        transformc(p0,q->b,p->u,p->v,p->w);
  668.        vecadd(p0,p->b,p0);
  669.        transformc(px,q->u,p->u,p->v,p->w);
  670.        transformc(py,q->v,p->u,p->v,p->w);
  671.        transformc(pz,q->w,p->u,p->v,p->w);
  672.       }
  673.  
  674.     q=pv->bound;
  675.     /* d is maximal distance from p->u */
  676.     db=dist2(q->u,p0);
  677.     d=fabs(dist2(q->u,px))+fabs(dist2(q->u,py))+fabs(dist2(q->u,pz));
  678.     if(dx0>db-d || !n) dx0=db-d; if(dx1<db+d || !n) dx1=db+d;
  679.  
  680.     db=dist2(q->v,p0);
  681.     d=fabs(dist2(q->v,px))+fabs(dist2(q->v,py))+fabs(dist2(q->v,pz));
  682.     if(dy0>db-d || !n) dy0=db-d; if(dy1<db+d || !n) dy1=db+d;
  683.  
  684.     db=dist2(q->w,p0);
  685.     d=fabs(dist2(q->w,px))+fabs(dist2(q->w,py))+fabs(dist2(q->w,pz));
  686.     if(dz0>db-d || !n) dz0=db-d; if(dz1<db+d || !n) dz1=db+d;
  687.    }
  688.  
  689.  q=pv->bound;
  690.  db=(dx0+dx1)/2; d=(dx1-dx0)/2;
  691.  vecscale(q->b,db,q->u); vecscale(q->u,d,q->u);
  692.  db=(dy0+dy1)/2; d=(dy1-dy0)/2;
  693.  vecscale(p0,db,q->v); vecadd(q->b,p0,q->b); vecscale(q->v,d,q->v);
  694.  db=(dz0+dz1)/2; d=(dz1-dz0)/2;
  695.  vecscale(p0,db,q->w); vecadd(q->b,p0,q->b); vecscale(q->w,d,q->w);
  696.  return(q);
  697. }
  698.  
  699.  
  700. /* automatic bound                                              */
  701. POV_OBJ *bound_obj(POV_OBJ *pv)
  702. {
  703.  char *s; int n;
  704.  POV_OBJ *q,*pp;
  705.  double d,vol,a,b,c;
  706.  VECTOR v,vb,vx,vy,vz;
  707.  
  708.  q=pv->bound;
  709.  if(q!=(POV_OBJ *)NULL) return(q);
  710.  pv->bound=new_obj();
  711.  pp=pv->bound;
  712.  
  713.  switch(pv->c)
  714.    {
  715.     case 0: /* primitive */
  716.        break;
  717.  
  718.     default:
  719.     case 1:  /* union */
  720.        for(s=pv->s;*s;s+=5)
  721.      { n=get4hex(s+1);
  722.        q=obj_all[n];
  723.        if((q->c!=0) && (q->bound==(POV_OBJ *)NULL)) bound_obj(q);
  724.      }
  725.  
  726.        vol=-1;
  727.        for(v[0]=0; v[0]<M_PI*5/12; v[0]+=M_PI/6)
  728.      for(v[1]=0; v[1]<M_PI*5/12; v[1]+=M_PI/6)
  729.        for(v[2]=0; v[2]<M_PI*5/12; v[2]+=M_PI/6)
  730.          {
  731.           q=cp_tmp(pp);
  732.           rotxyz(q->u,v,q->u);
  733.           rotxyz(q->v,v,q->v);
  734.           rotxyz(q->w,v,q->w);
  735.           pv->bound=q;
  736.           q=fit_obj(pv);
  737.           a=vecabs(q->u); b=vecabs(q->v); c=vecabs(q->w);
  738.           d=a*b+a*c+b*c; /* area */
  739.           if(d<vol || vol<0)
  740.         { vol=d;
  741.           vecasn(vb,q->b); vecasn(vx,q->u);
  742.           vecasn(vy,q->v); vecasn(vz,q->w);
  743.         }
  744.          }
  745.        pv->bound=pp;
  746.        vecasn(pp->b,vb);        vecscale(pp->u,1.01,vx);
  747.        vecscale(pp->v,1.01,vy); vecscale(pp->w,1.01,vz);
  748.        break;
  749.  
  750.     case 2: /* intersection, looking for the smallest bound */
  751.        for(s=pv->s,vol=-1;*s;s+=5)
  752.      { n=get4hex(s+1);
  753.        q=obj_all[n];
  754.        if((q->c!=0) && (q->bound==(POV_OBJ *)NULL)) bound_obj(q);
  755.        if(q->bound!=(POV_OBJ *)NULL) q=q->bound;
  756.        a=vecabs(q->u); b=vecabs(q->v); c=vecabs(q->w);
  757.        d=a*b+a*c+b*c; /* area */
  758.        if(d<vol || vol<0)
  759.          { vol=d;
  760.            vecasn(vb,q->b); vecasn(vx,q->u);
  761.            vecasn(vy,q->v); vecasn(vz,q->w);
  762.          }
  763.      }
  764.        vecasn(pp->b,vb);        vecscale(pp->u,1.01,vx);
  765.        vecscale(pp->v,1.01,vy); vecscale(pp->w,1.01,vz);
  766.        break;
  767.  
  768.     case 3: /* difference */
  769.        for(s=pv->s;*s;s+=5)
  770.      { n=get4hex(s+1);
  771.        q=obj_all[n];
  772.        if((q->c!=0) && (q->bound==(POV_OBJ *)NULL)) bound_obj(q);
  773.      }
  774.  
  775.        n=get4hex((pv->s)+1);
  776.        q=obj_all[n];
  777.        if(q->bound!=(POV_OBJ *)NULL) q=q->bound;
  778.        vecasn(pp->b,q->b);
  779.        vecasn(pp->u,q->u);
  780.        vecasn(pp->v,q->v);
  781.        vecasn(pp->w,q->w);
  782.        break;
  783.  
  784.    }
  785.  pp->s=cp_str("box {<-1,-1,-1>< 1, 1, 1>}");
  786.  return(pp);
  787. }
  788.  
  789.  
  790.  
  791. /* Print Object                            */
  792. static int pr_level=0;
  793. #define PPR for(i=0;i<15 && i<pr_level;i++) putc(' ',fep),putc(' ',fep);
  794. void print_obj( FILE *fep, POV_OBJ *pv )
  795. {
  796.  VECTOR v;
  797.  int n,i;
  798.  char *s;
  799.  static char msg[]="Printing object or CSG object";
  800.  
  801.  
  802.  switch(pv->c)
  803.    {
  804.     case 1:  PPR; fprintf(fep,"union"); goto la_po1;
  805.     case 2:  PPR; fprintf(fep,"intersection"); goto la_po1;
  806.     case 3:  PPR; fprintf(fep,"difference"); goto la_po1;
  807.  
  808.     la_po1:    fprintf(fep," {\n");
  809.            if(pv->s!=(char *)NULL)
  810.          for(s=pv->s;*s;s+=5)
  811.            {
  812.             n=GET4HEX(s+1);
  813.             if((n<0) || (n>=PSIZE) || (obj_all[n]==(POV_OBJ *)NULL))
  814.                t_error(msg,3);
  815.             pr_level++;
  816.             print_obj(fep,obj_all[n]);
  817.             pr_level--;
  818.            }
  819.            goto la_po2;
  820.     default:
  821.     case 0:  PPR; fprintf(fep,"object { ");
  822.          if(pv->s!=(char *)NULL) fprintf(fep,"%s\n",pv->s);
  823.          else fprintf(fep,"sphere { <0,0,0>,1 }\n");
  824.          goto la_po2;
  825.     case -1: PPR; fprintf(fep,"texture { ");
  826.          if(pv->s!=(char *)NULL) fprintf(fep,"%s\n",pv->s);
  827.          else fprintf(fep,"MyTexture\n");
  828.          goto la_po3;
  829.     la_po2:
  830.          if(pv->bound!=(POV_OBJ *)NULL)
  831.            {
  832.         pr_level++;
  833.         PPR; fprintf(fep,"bounded_by {\n");
  834.         pr_level++; print_obj(fep,pv->bound); pr_level--;
  835.         PPR; fprintf(fep,"}\n");
  836.         PPR; fprintf(fep,"clipped_by { bounded_by }\n");
  837.         pr_level--;
  838.            }
  839.          if(pv->tex!=(POV_OBJ *)NULL)
  840.            {
  841.         n=(pv->tex)->c; (pv->tex)->c=-1;
  842.         pr_level++; print_obj(fep,pv->tex); pr_level--;
  843.         (pv->tex)->c=n;
  844.            }
  845.  
  846.     la_po3:  v[0]=vecabs(pv->u); v[1]=vecabs(pv->v); v[2]=vecabs(pv->w);
  847.          if((v[0]!=1) || (v[1]!=1) || (v[2]!=1))
  848.            { PPR; fprintf(fep," scale <%G,%G,%G>\n",v[0],v[1],v[2]); }
  849.          if(vecabs(pv->u)<=0) t_error(msg,3);
  850.          if(vecabs(pv->v)<=0) t_error(msg,3);
  851.          if(vecabs(pv->w)<=0) t_error(msg,3);
  852.          getrotxyz(v,pv->u,pv->v,pv->w);
  853.          if((v[0]!=0) || (v[1]!=0) || (v[2]!=0))
  854.            {
  855.         PPR; fprintf(fep," rotate <%G,%G,%G>\n",
  856.                   v[0]*180/M_PI,v[1]*180/M_PI,v[2]*180/M_PI);
  857.            }
  858.          vecasn(v,pv->b);
  859.          if((v[0]!=0) || (v[1]!=0) || (v[2]!=0))
  860.            { PPR;
  861.          fprintf(fep," translate <%G,%G,%G> \n", v[0],v[1],v[2]); }
  862.          PPR; fprintf(fep,"}\n");
  863.          break;
  864.    }
  865.  return;
  866. }
  867.  
  868.